package com.asialjim.wechat.official.authpage.impl;

import com.asialjim.wechat.apiservice.constant.WeChatConstants;
import com.asialjim.wechat.apiservice.enumeration.WeChatApiReturnEnumeration;
import com.asialjim.wechat.apiservice.exception.WeChatApiException;
import com.asialjim.wechat.core.bean.WeChatBean;
import com.asialjim.wechat.core.executor.WeChatApiExecutor;
import com.asialjim.wechat.database.DataBaseService;
import com.asialjim.wechat.official.api.OfficialApi;
import com.asialjim.wechat.official.api.wechatuser.GetAccessTokenForUserApiRequest;
import com.asialjim.wechat.official.api.wechatuser.GetAccessTokenForUserApiResponse;
import com.asialjim.wechat.official.authpage.AuthPage;
import com.asialjim.wechat.official.authpage.AuthPageService;
import com.asialjim.wechat.pojo.account.WeChatAccount;
import com.asialjim.wechat.pojo.account.WeChatAccountHolder;
import com.asialjim.wechat.utils.JsonUtils;
import com.asialjim.wechat.wechataccount.WeChatAccountService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import lombok.var;
import org.apache.commons.lang3.StringUtils;
import java.util.*;

/**
 * <h1><em>ASIAL JIM JAVA DOC</em></h1><hr/>
 * <h2>CLASS DESCRIPTION <i>[ NAME: AuthPageServiceImpl ]</i></h2><strong>
 * <p> auth page service
 * </strong><p><p><em>Copyright &copy; Asial Jim Co., LTD</em><hr/>
 *
 * @author Asial Jim &nbsp;&nbsp; <span>Email:<a href="mailto:asialjim@hotmail.com">asialjim@hotmail.com</a> &nbsp;&nbsp; <a href="asialjim@qq.com">asialjim@qq.com</a></span>
 * @version 1.0.0
 * @since 2021/4/5   &nbsp;&nbsp; JDK 8
 */
@Slf4j
@AllArgsConstructor
public class AuthPageServiceImpl implements AuthPageService, WeChatBean {
    private final WeChatApiExecutor apiExecutor;
    private final DataBaseService dataBaseService;
    private final WeChatAccountService weChatAccountService;
    @Override
    public String redirectUrl(String code, String state) {
        log.info("\r\n\tHANDLE AUTH PAGE, CODE:[{}],STATE:[{}}",code,state);
        AuthPage authPage = Optional.ofNullable(dataBaseService.selectById(AuthPage.class, state)).orElse(new AuthPage());
        log.info("\r\n\tQUERY AUTH PAGE SOURCE BY STATE:[{}],RESULT:[{}]",state,authPage);
        String appId = authPage.getAppid();
        String url = authPage.getUrl();
        if (StringUtils.isBlank(appId)){
            log.warn("\r\n\tthere is no app id for state:[{}]",state);
            // todo throw an exception
        }
        if (StringUtils.isBlank(url)){
            log.warn("\r\n\tthere is no redirect url for state:[{}]",state);
            // todo throw an exception
        }

        StringJoiner urlBuilder = new StringJoiner(url);

        String param = authPage.getParam();
        if (StringUtils.isNotBlank(param)){
            Map<String, Object> paramMap = JsonUtils.jsonToMap(param);
            assert paramMap != null;
            paramMap.entrySet().stream()
                    .filter(entry -> StringUtils.isNotBlank(entry.getKey()) && StringUtils.isNotBlank((String)entry.getValue()))
                    .forEach(entry -> urlBuilder.add("&").add(entry.getKey()).add("=").add((String)entry.getValue()));
        }


        WeChatAccount weChatAccount = Optional.ofNullable(dataBaseService.selectOne(WeChatAccount.builder().appId(appId).build())).orElse(WeChatAccount.builder().build());
        String appSecret = weChatAccount.getAppSecret();
        if (StringUtils.isBlank(appSecret)){
            log.warn("\r\n\tthe secret is empty for we-chat appid:[{}]",appId);
            // todo throw an exception
        }

        GetAccessTokenForUserApiResponse response = apiExecutor.execute(OfficialApi.GET_ACCESS_TOKEN_FOR_USER, GetAccessTokenForUserApiRequest.UrlParam.builder().appid(appId).secret(appSecret).code(code).build(), GetAccessTokenForUserApiResponse.class).parse();

        urlBuilder.add("&OpenId=").add(response.getOpenid()).add("&appId=").add(appId);
        return urlBuilder.toString().replaceFirst("&","?");
    }

    @Override
    public AuthPage addAuthPage(String appId, String url,  String param, Integer expires) {
        if (StringUtils.isBlank(appId)){
            appId= weChatAccountService.currentAppId();
            if (StringUtils.isBlank(appId)) {
                WeChatApiException.cast(WeChatApiReturnEnumeration.CODE_40086);
            }
        }

        String state = UUID.randomUUID().toString().replaceAll("-", "");
        var authPage = new AuthPage();
        authPage.setAppid(appId);
        authPage.setId(state);
        authPage.setExpires(expires);
        authPage.setUrl(url);
        authPage.setParam(param);
        int insert = dataBaseService.insert(authPage);
        authPage.setCreateTime(new Date());
        log.info("\r\n\tADD AUTH PAGE:[{}],RESULT:[{}]",authPage,insert);
        WeChatAccount weChatAccount = WeChatAccountHolder.get();
        String authPageUrl = String.format(WeChatConstants.WeChatApiUrl.GET_AUTH_PAGE_URL, appId, weChatAccount.getUrl() + "/redirect", state);
        authPage.setAuthUrl(authPageUrl);
        return authPage;
    }
}
